home *** CD-ROM | disk | FTP | other *** search
/ MACD 5 / MACD 5.bin / workbench / libs / unixlib.lha / unix / src / select.c < prev    next >
C/C++ Source or Header  |  1996-11-13  |  2KB  |  104 lines

  1. #include "amiga.h"
  2. #include "files.h"
  3. #include "signals.h"
  4. #include "timers.h"
  5. #include <string.h>
  6. #include <sys/time.h>
  7. #include <amiga/ioctl.h>
  8.  
  9. int
  10. select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *to)
  11. {
  12.     int i, j, fdcount, err = 0;
  13.     int poll = to && to->tv_sec == 0 && to->tv_usec == 0;
  14.     ULONG eventmask, sigs;
  15.     int *rd, *wr, *ex, *ck;
  16.     struct fileinfo **fi = calloc(5*nfds, sizeof(struct fileinfo *));
  17.  
  18.     if (!fi) {
  19.     errno = ENOMEM;
  20.     return -1;
  21.     }
  22.     rd = (int *)(fi + nfds);
  23.     wr = rd + nfds;
  24.     ex = wr + nfds;
  25.     ck = ex + nfds;
  26.  
  27.     for (i = 0, j = 0; i < nfds; i++) {
  28.     __chkabort();
  29.  
  30.     if (rfds && FD_ISSET(i, rfds)) {
  31.         rd[j] = i;
  32.         ck[j] |= 1;
  33.     }
  34.     if (wfds && FD_ISSET(i, wfds)) {
  35.         wr[j] = i;
  36.         ck[j] |= 2;
  37.     }
  38.     if (efds && FD_ISSET(i, efds)) {
  39.         ex[j] = i;
  40.         ck[j] |= 4;
  41.     }
  42.  
  43.     if (ck[j]) {
  44.         fi[j] = _find_fd(i);
  45.  
  46.         if (!fi[j]) {
  47.         free(fi);
  48.         return -1;
  49.         }
  50.         if (((ck[j] & 1) && !(fi[j]->flags & FI_READ)) ||
  51.             ((ck[j] & 2) && !(fi[j]->flags & FI_WRITE))) {
  52.         errno = EACCES;
  53.         free(fi);
  54.         return -1;
  55.         }
  56.         j++;
  57.     }
  58.     }
  59.  
  60.     if (to)
  61.     _timer_start(_odd_timer, to->tv_sec, to->tv_usec);
  62.     else
  63.     _timer_abort(_odd_timer);
  64.  
  65.     fdcount = 0;
  66.  
  67.     do {
  68.     eventmask = 0;
  69.     for (i = 0; i < j; i++)
  70.         eventmask |= fi[i]->select_start(fi[i]->userinfo,
  71.             ck[i] & 1, ck[i] & 2, ck[i] & 4);
  72.  
  73.     if (eventmask == -1 || poll)    /* Don't wait */
  74.         sigs = _check_signals(0);
  75.     else                /* Wait */
  76.         sigs = _wait_signals(_odd_sig | eventmask);
  77.  
  78.     for (i = 0; i < j; i++) {
  79.         int r = ck[i] & 1, w = ck[i] & 2, e = ck[i] & 4;
  80.  
  81.         if (fi[i]->select_poll(fi[i]->userinfo, &r, &w, &e) < 0)
  82.         err = 1;
  83.         if (!err) {
  84.         if (!r && rfds)
  85.             FD_CLR(rd[i], rfds);
  86.         if (!w && wfds)
  87.             FD_CLR(wr[i], wfds);
  88.         if (!e && efds)
  89.             FD_CLR(ex[i], efds);
  90.         if (r || w || e)
  91.             fdcount++;
  92.         }
  93.     }
  94.     _handle_signals(sigs);
  95.     } while (fdcount == 0 && !_timer_expired(_odd_timer) && !poll && !err);
  96.  
  97.     free(fi);
  98.  
  99.     if (err)
  100.     return -1;
  101.  
  102.     return fdcount;
  103. }
  104.